package com.wlanauth.web.action;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.xwork.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.wlanauth.core.criteria.GeneralCriteria;
import com.wlanauth.core.criteria.GeneralCriteriaQuery;
import com.wlanauth.core.criteria.GeneralCriteriaResult;
import com.wlanauth.domain.manage.Operator;
import com.wlanauth.domain.manage.User;
import com.wlanauth.domain.radius.RadAcct;
import com.wlanauth.service.radius.RadAcctService;
import com.wlanauth.web.core.BaseActionSupport;
import com.wlanauth.web.core.JsonResult;
import com.wlanauth.web.util.RadiusUtils;
/**
 * 计费
 * @author zz
 * @date 2012-5-17
 * @email charles.zz.life@gmail.com
 */
public class RadAcctAction extends BaseActionSupport {

	private static final long serialVersionUID = 1L;
	
	private RadAcct entity;//实体类
	
	private int fetchHistorySpan = 10;
	/**
	 * --------统计查询时用
	 */
	private Integer year;
	private Integer month;
	private Integer day;
	
	private String parentDateStr;
	
	private RadAcctService radAcctService;
	public String list(){
		GeneralCriteria criteria = this.buildWebQueryCriteria(RadAcct.class);
		if(entity!=null){
			if(entity.getUsername()!=null){
				criteria.add(Restrictions.eq("username", entity.getUsername()));
			}
		}
		criteria.addOrder(Order.desc("acctStartTime"));
		GeneralCriteriaResult<RadAcct> result = criteria.executeQuery();
		this.jsonResult = new JsonResult(this,result,true);
		return this.actionJsonResult();
	}
	
	/**
	 * 用户流量列表
	 * @return
	 */
	
	public String listUserAcct(){
		//权限
		boolean flag = false;
		User u = null;
		Operator oper = this.getCurrentOperator();
		if(oper!=null){
			flag = true;
		} else {
			u = this.getCurrentUser();
			if(u!=null&&u.getBindIP().equals(entity.getUsername())){
				flag = true;
			}
		} 
		if(!flag){
			this.jsonResult = new JsonResult(this,"对不起，您无权查看该用户流量详情",false);
			return this.actionJsonResult();
		} 
		if(u == null){
			GeneralCriteria criteria = new GeneralCriteria(User.class);
			criteria.add(Restrictions.eq("bindIP", entity.getUsername()));
			GeneralCriteriaResult<User> result = criteria.executeQuery();
			if(result.getData()==null||result.getData().size()<1){
				this.jsonResult = new JsonResult(this,"用户不存在或已删除",false);
				return this.actionJsonResult();
			}
			u =  result.getData().get(0);
		}
		GeneralCriteria criteria = this.buildWebQueryCriteria(RadAcct.class);
		criteria.add(Restrictions.eq("username", u.getBindIP()));
		criteria.add(Restrictions.gt("acctStartTime", u.getActiveTime()));
		criteria.addOrder(Order.desc("acctStartTime"));
		GeneralCriteriaResult<RadAcct> result = criteria.executeQuery();
		if(result.getData()!=null){
			for(RadAcct acct:result.getData()){
				Long inOct = acct.getAcctInputOctets()==null?0L:acct.getAcctInputOctets();
				Long outOct = acct.getAcctOutputOctets() == null?0L:acct.getAcctOutputOctets();
				acct.setAcctInputOctets(RadiusUtils.getViewOct(BigDecimal.valueOf(inOct)).longValue());
				acct.setAcctOutputOctets(RadiusUtils.getViewOct(BigDecimal.valueOf(outOct)).longValue());
				
			}
		}
		this.jsonResult = new JsonResult(this,result.getData(),result.getTotal());
		return this.actionJsonResult();
	}
	
	
	public String currentUserAndOctets(){
		Map<String,Object> map = getActiveStatus(new Date());;
		this.jsonResult = new JsonResult(this,map,true);
		return this.actionJsonResult();
	}
	
	public String historyUserAndOcts(){
		Calendar c = Calendar.getInstance();
		List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
		c.add(Calendar.MINUTE,0-this.fetchHistorySpan);
		for(int i=1;i<=this.fetchHistorySpan;i++){
			c.add(Calendar.MINUTE, 1);
			Map<String,Object> r = getActiveStatus(c.getTime());
			result.add(r);
		}
		this.jsonResult = new JsonResult(this,result,Long.parseLong(""+result.size()));
		return this.actionJsonResult();
	}
	
	
	/**
	 * 获取活动信息
	 * @param time
	 * @return
	 */
	private Map<String,Object> getActiveStatus(Date time){
		DetachedCriteria criteria = DetachedCriteria.forClass(RadAcct.class);
		
		criteria.add(Restrictions.and(Restrictions.le("acctStartTime", time), 
				Restrictions.or(Restrictions.gt("acctStopTime", time), Restrictions.isNull("acctStopTime"))));
		criteria.add(Restrictions.isNull("acctStopTime"));
		criteria.setProjection(Projections.projectionList()
				.add(Projections.sum("acctInputOctets"))
				.add(Projections.sum("acctOutputOctets"))
				.add(Projections.rowCount()));
		
		GeneralCriteriaQuery query = new GeneralCriteriaQuery();
		List<Object[]> list = query.execute(criteria);
		Long sumOct = 0L,sumUser = 0L;
		if(list != null&&list.size()>0){
			Object[] obj = list.get(0);
			Long in = 0L,out=0L;
			if(obj!=null&&obj.length==3){
				if(obj[0]!=null){
					in = (Long)obj[0];
				}
				if(obj[1]!=null){
					out = (Long)obj[1];
				}
				if(obj[2]!=null){
					sumUser = Long.parseLong(""+obj[2]);
				}
				sumOct = in+out;
			}
			
		}
		Map<String,Object> map = new HashMap<String,Object>();
		
		map.put("time", time.getTime());
		map.put("activeOctets", sumOct);
		map.put("activeOctets2", RadiusUtils.getViewOct(BigDecimal.valueOf(sumOct)).longValue());
		map.put("onlineNum", sumUser);
		return map;
	}

	/**
	 * 用于 当日、当月、当本度统计
	 * @return
	 */
	public String octetAndUsers(){
		
		//约定：year>0时，为取年;month>0时为取月;day>0时，取日
		StatisticsOctetAndUserVO totalVO = new StatisticsOctetAndUserVO();
		List<StatisticsOctetAndUserVO> list = null;
		Calendar c = Calendar.getInstance();
		if(this.year!=null&&this.year>0){
			String dateStr = ""+c.get(Calendar.YEAR);
			list = this.getOctetAndUsers("%Y-%m","%Y",dateStr);
			totalVO =  this.getOctetAndUsers("%Y",dateStr);
		} else if(this.month!=null&&this.month>0){
			int month = c.get(Calendar.MONTH)+1;
			String dateStr = ""+c.get(Calendar.YEAR)+"-"+StringUtils.leftPad(""+month, 2,'0');
			list = this.getOctetAndUsers("%Y-%m-%d","%Y-%m",dateStr);
			totalVO =  this.getOctetAndUsers("%Y-%m",dateStr);
		} else if(this.day!=null&&this.day>0){
			int month = c.get(Calendar.MONTH)+1;
			int day = c.get(Calendar.DAY_OF_MONTH);
			String dateStr = ""+c.get(Calendar.YEAR)+"-"+StringUtils.leftPad(""+month, 2,'0')+"-"+StringUtils.leftPad(""+day,2,'0');
			list = this.getOctetAndUsers("%Y-%m-%d-%H","%Y-%m-%d",dateStr);
			totalVO =  this.getOctetAndUsers("%Y-%m-%d",dateStr);
		}
		this.jsonResult = new JsonResult(this,list,true);
		this.jsonResult.setData(totalVO);
		return this.actionJsonResult();
		
	}
	
	
	
	/**
	 * 当年月流量
	 * @author zz
	 * @deprecated see octetAndUsers 
	 * @return
	 */
	public String monthsOctet(){
		StatisticsOctetAndUserVO currentMonthVO = new StatisticsOctetAndUserVO();
		
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
		
		Calendar c = Calendar.getInstance();
		
		String currentMonthStr = df.format(c.getTime());
		
		//默认
		currentMonthVO.setDate(currentMonthStr);
		
		int year = c.get(Calendar.YEAR);
		c.setTimeInMillis(0);
		c.set(Calendar.YEAR, year);
		List<StatisticsOctetAndUserVO> list = this.getOctetAndUsers("%Y-%m","%Y",""+c.get(Calendar.YEAR));
		
		this.jsonResult = new JsonResult(this,list,true);
		return this.actionJsonResult();
		
	}
	/**
	 * 简单统计
	 * @return
	 */
	public String simpleAnalysis(){
		String groupFormat = "%Y";
		String conditionFormat = "";
		String dateStr = "";
		Calendar c = Calendar.getInstance();
		c.set(Calendar.MILLISECOND, 0);//计是原点
		if(this.year!=null){
			groupFormat="%Y";
			conditionFormat += "-%Y";
			dateStr = "-"+StringUtils.leftPad(""+this.year, 4,'0');
			c.set(Calendar.YEAR, this.year);
		}
		if(this.month!=null){
			groupFormat="%Y-%m";
			conditionFormat += "-%m";
			dateStr += "-"+StringUtils.leftPad(""+this.month, 2,'0');
			c.set(Calendar.MONTH,this.month);
		}
		if(this.day!=null){
			groupFormat="%Y-%m-%d";
			conditionFormat+= "-%d";
			dateStr += "-"+StringUtils.leftPad(""+this.day, 2,'0');
			c.set(Calendar.DAY_OF_MONTH, this.day);
		}
		conditionFormat =( conditionFormat ==""?"-":conditionFormat.substring(1));
		dateStr = (dateStr==""?"-":dateStr.substring(1));
	
		List<StatisticsOctetAndUserVO> list = this.getOctetAndUsers(groupFormat,conditionFormat,dateStr);
		this.jsonResult = new JsonResult(this,list,true);
		return this.actionJsonResult();
		
	}
	
	public String simpleAnalysisChildren(){
		List<StatisticsOctetAndUserVO> list = null;
		if(this.parentDateStr.length()==4){ //取年
			list = this.getOctetAndUsers("%Y-%m","%Y",this.parentDateStr);
			
		} else if(this.parentDateStr.length()==7){ //取月
			list = this.getOctetAndUsers("%Y-%m-%d","%Y-%m",this.parentDateStr);
			
		} else {
			list = this.getOctetAndUsers("%Y-%m-%d-%H","%Y-%m-%d",this.parentDateStr);
		}
		
		this.jsonResult = new JsonResult(this,list,true);
		return this.actionJsonResult();
	}
	
	private StatisticsOctetAndUserVO getOctetAndUsers(String conditonFormat,String dateStr){
		List<StatisticsOctetAndUserVO> list = this.getOctetAndUsers(conditonFormat, conditonFormat, dateStr);
		if(list==null||list.size()<1) return null;
		return list.get(0);
	}
	/**
	 * 获取特定时间段流量及用户信息
	 * @param start //开始时间
	 * @param end	//结束时间
	 * @param groupType //分组类型:YEAR:MONTH:DAY
	 * @return
	 */
	private List<StatisticsOctetAndUserVO> getOctetAndUsers(String groupFormat,String conditonFormat,String dateStr){
		String allowGroup = "|%Y-%m-%d-%H|%Y-%m-%d|%Y-%m|%Y-%d|%m-%d|%Y|%m|%d";
		if(!allowGroup.contains("|"+groupFormat)){
			throw new IllegalArgumentException("允许格式:"+allowGroup);
		}
		/**
		 * 	SELECT COUNT(DISTINCT a.username) c_u,SUM(a.acctInputOctets) c_in ,SUM(a.acctOutputOctets) c_out,

			(SELECT COUNT(DISTINCT username) FROM radacct b WHERE 
			DATE_FORMAT(a.acctstarttime,'%Y')>b.acctstarttime AND (b.acctstoptime>=DATE_FORMAT(a.acctstarttime,'%Y') OR b.ACCTSTOPTIME IS NULL)
			) b_u,
			(SELECT SUM(b.acctInputOctets) FROM radacct b WHERE 
			DATE_FORMAT(a.acctstarttime,'%Y')>b.acctstarttime AND (b.acctstoptime>=DATE_FORMAT(a.acctstarttime,'%Y') OR b.ACCTSTOPTIME IS NULL)
			) b_in,
			(SELECT SUM(b.acctOutputOctets) FROM radacct b WHERE 
			DATE_FORMAT(a.acctstarttime,'%Y')>b.acctstarttime AND (b.acctstoptime>=DATE_FORMAT(a.acctstarttime,'%Y') OR b.ACCTSTOPTIME IS NULL)
			) b_out,
			DATE_FORMAT(a.acctstarttime,'%Y')
			
			FROM radacct a
			WHERE DATE_FORMAT(a.acctstarttime,'0') = '0'
			GROUP BY DATE_FORMAT(a.acctstarttime,'%Y')
			
			
			SELECT DATE_FORMAT(a.acctstarttime,'') FROM radacct a
		 */
		@SuppressWarnings("unchecked")
		List<Object[]> data = (List<Object[]>) radAcctService.queryByDateGroupAndDateStr(groupFormat, conditonFormat, dateStr);
		List<StatisticsOctetAndUserVO> list = new ArrayList<StatisticsOctetAndUserVO>();
		if(data!=null){
			for(Object[] cols:data){
				long c_inOct = 0,c_outOct = 0,c_sumUser = 0L;
				long l_inOct = 0,l_outOct = 0,l_sumUser = 0L;
				long p_inOct = 0,p_outOct = 0,p_sumUser = 0L;//交集
				c_sumUser = valueOf(cols[1]);
				c_inOct = valueOf(cols[2]);
				c_outOct = valueOf(cols[3]);
				//过渡用户
				l_sumUser = valueOf(cols[4]);
				l_inOct =valueOf(cols[5]);
				l_outOct = valueOf(cols[6]);
				
				p_sumUser = valueOf(cols[7]);
				p_inOct = valueOf(cols[8]);
				p_outOct = valueOf(cols[9]);
				
				BigDecimal sumOct = BigDecimal.valueOf(c_inOct+c_outOct+l_inOct+l_outOct-p_inOct-p_outOct);
				StatisticsOctetAndUserVO vo = new StatisticsOctetAndUserVO();
				vo.setDate(cols[0].toString());
				vo.setSumOct(sumOct.longValue());
				vo.setSumOct2(RadiusUtils.getViewOct(sumOct).longValue());
				vo.setSumUser(c_sumUser+l_sumUser-p_sumUser);
				list.add(vo);
			}
		}
		return list;
	}
	private long valueOf(Object l){
		return l==null?0:(Long.valueOf(l.toString()));
	}

	public void setEntity(RadAcct entity) {
		this.entity = entity;
	}

	public RadAcct getEntity() {
		return entity;
	}

	public int getFetchHistorySpan() {
		return fetchHistorySpan;
	}

	public void setFetchHistorySpan(int fetchHistorySpan) {
		this.fetchHistorySpan = fetchHistorySpan;
	}
	
	public void setYear(Integer year) {
		this.year = year;
	}

	public void setMonth(Integer month) {
		this.month = month;
	}

	public void setDay(Integer day) {
		this.day = day;
	}

	public String getParentDateStr() {
		return parentDateStr;
	}

	public void setParentDateStr(String parentDateStr) {
		this.parentDateStr = parentDateStr;
	}

	public RadAcctService getRadAcctService() {
		return radAcctService;
	}

	public void setRadAcctService(RadAcctService radAcctService) {
		this.radAcctService = radAcctService;
	}

	/**
	 * 统计流量及用户信息
	 * @author zz
	 *
	 */
	public static class StatisticsOctetAndUserVO {
		
		private String date;//日期或时间
		private long sumOct;//流量
		private long sumOct2;//计费流量
		private long sumUser;//总用户
		public String getDate() {
			return date;
		}
		public void setDate(String date) {
			this.date = date;
		}
		public long getSumOct() {
			return sumOct;
		}
		public void setSumOct(long sumOct) {
			this.sumOct = sumOct;
		}
		public long getSumOct2() {
			return sumOct2;
		}
		public void setSumOct2(long sumOct2) {
			this.sumOct2 = sumOct2;
		}
		public long getSumUser() {
			return sumUser;
		}
		public void setSumUser(long sumUser) {
			this.sumUser = sumUser;
		}
		
		
	}
}
